package com.zj.leetcode.medium.hash;

import java.util.HashMap;

/**
 * @program: algorithm
 * @description: 分数到小数
 * 166 fraction-to-recurring-decimal
 * @author: Zhang Bo
 * @create: 2022-01-14 17:05
 **/
public class FractionToRecurringDecimal {
    public static void main(String[] args) {
//        int numerator = 1, denominator = 2;
//        int numerator = 2, denominator = 1;
//        int numerator = 2, denominator = 3;
//        int numerator = 1, denominator = 6;
//        int numerator = -50, denominator = 8;
        int numerator = -1, denominator = -2147483648;
        Solution solution = new FractionToRecurringDecimal().new Solution();
        System.out.println(solution.fractionToDecimal(numerator, denominator));

    }

    //leetcode submit region begin(Prohibit modification and deletion)
    class Solution {


        /**
         * 定理，能用分数表示的数，一定是有限小数或者是无限循环小数
         *
         * @param numerator
         * @param denominator
         * @return
         */
        public String fractionToDecimal(int numerator, int denominator) {

            StringBuilder sb = new StringBuilder();
            //为了防止越界，先转化成long类型再去判断结果是否小于0
            if ((long) numerator * (long) denominator < 0) {
                sb.append("-");
            }

            // 将参数转化成正数再向后进行
            // 不然会出现下面的情景
            //输入：numerator = -1, denominator = 2
            //输出："0.-5"
            long nL = Math.abs((long) numerator);
            long dL = Math.abs((long) denominator);
            //找大于零的值。
            sb.append(nL / dL);


            //这里就是计算从小数点之前的长度
            //如：0.5， i = 2
            //   23.43 i = 3
            int i = sb.length() + 1;
            HashMap<Long, Integer> map = new HashMap<>();
            while ((nL = nL % dL * 10) != 0) {
                //首次循环要加上小数点 .
                if (i == sb.length() + 1) {
                    sb.append(".");
                }

                long temp = nL / dL;

                //将该位的数放到map中
                Integer flag = map.put(nL, i);

                //如果这个数被放到过map中，说明该数是第二次出现，那么说明已经进入第二次循环了。
                //所以将flag 到 length 中的数字加入括号，并直接返回即可。
                //注意：该解法应该是有个bug：
                // 当遇到类似于 0.23233333...这样的数，会首先检测到小数点后第三位的 2 已经出现过了，
                // 所以会将小数点后第一个 2 当做循环的开始位，所以会得到这样的结果 0.(23),
                // 不过 leetcode 好像并没有这样的用例，或者还是说分数没有这样的值，哈哈哈，真幸运！
                if (flag != null) {
                    sb.insert(flag, "(");
                    sb.append(")");
                    break;
                }

                sb.append(temp);
                i++;
            }
            return sb.toString();
        }

        /**
         * 无注释版
         * @param numerator
         * @param denominator
         * @return
         */
        public String fractionToDecimal02(int numerator, int denominator) {

            StringBuilder sb = new StringBuilder();
            //为了防止越界，先转化成long类型再去判断结果是否小于0
            if ((long) numerator * (long) denominator < 0) {
                sb.append("-");
            }

            // 将参数转化成正数再向后进行
            // 不然会出现下面的情景
            //输入：numerator = -1, denominator = 2
            //输出："0.-5"
            long nL = Math.abs((long) numerator);
            long dL = Math.abs((long) denominator);
            //找大于零的值。
            sb.append(nL / dL);


            int i = sb.length() + 1;
            HashMap<Long, Integer> map = new HashMap<>();
            while ((nL = nL % dL * 10) != 0) {
                if (i == sb.length() + 1) {
                    sb.append(".");
                }
                long temp = nL / dL;

                Integer flag = map.put(nL, i);
                if (flag != null) {
                    sb.insert(flag, "(");
                    sb.append(")");
                    break;
                }
                sb.append(temp);
                i++;
            }
            return sb.toString();
        }
    }
//leetcode submit region end(Prohibit modification and deletion)

}
